package com.shanjupay.merchant.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shanjupay.common.domain.BusinessException;
import com.shanjupay.common.domain.CommonErrorCode;
import com.shanjupay.common.util.PhoneUtil;
import com.shanjupay.common.util.StringUtil;
import com.shanjupay.merchant.api.MerchantService;
import com.shanjupay.merchant.api.dto.MerchantDTO;
import com.shanjupay.merchant.api.dto.StaffDTO;
import com.shanjupay.merchant.api.dto.StoreDTO;
import com.shanjupay.merchant.convert.MerchantConvert;
import com.shanjupay.merchant.convert.StaffConvert;
import com.shanjupay.merchant.convert.StoreConvert;
import com.shanjupay.merchant.entity.Merchant;
import com.shanjupay.merchant.entity.Staff;
import com.shanjupay.merchant.entity.Store;
import com.shanjupay.merchant.entity.StoreStaff;
import com.shanjupay.merchant.mapper.MerchantMapper;
import com.shanjupay.merchant.mapper.StaffMapper;
import com.shanjupay.merchant.mapper.StoreMapper;
import com.shanjupay.merchant.mapper.StoreStaffMapper;
import com.shanjupay.user.api.TenantService;
import com.shanjupay.user.api.dto.tenant.CreateTenantRequestDTO;
import com.shanjupay.user.api.dto.tenant.TenantDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * <h1>商户服务实现</h1>
 * @author lsy
 * @date 2020/05/08
 */
@org.apache.dubbo.config.annotation.Service
@Slf4j
public class MerchantServiceImpl implements MerchantService {

    @Autowired
    MerchantMapper merchantMapper;

    @Autowired
    StoreMapper storeMapper;

    @Autowired
    StaffMapper staffMapper;

    @Autowired
    StoreStaffMapper storeStaffMapper;

    @org.apache.dubbo.config.annotation.Reference
    TenantService tenantService;

    @Override
    public MerchantDTO queryMerchantById(Long id) {
        Merchant merchant = merchantMapper.selectById(id);

        // 使用MapStruct将entity转换成DTO
        return MerchantConvert.INSTANCE.entity2dto(merchant);
    }

    @Override
    public MerchantDTO createMerchant(MerchantDTO merchantDTO) throws BusinessException {
        // 参数校验
        if (merchantDTO == null) {
            throw new BusinessException(CommonErrorCode.E_100108);
        }

        // 手机号校验
        if (StringUtils.isBlank(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100112);
        }

        // 手机号码格式校验
        if (!PhoneUtil.isMatches(merchantDTO.getMobile())) {
            throw new BusinessException(CommonErrorCode.E_100109);
        }

        // 商户联系人非空校验
        if (StringUtil.isBlank(merchantDTO.getUsername())) {
            throw new BusinessException(CommonErrorCode.E_100110);
        }
        // 校验密码
        if (StringUtils.isBlank(merchantDTO.getPassword())) {
            throw new BusinessException(CommonErrorCode.E_100111);
        }
        // 校验商户手机号的唯一性， 根据手机号查询商户是否存在
        Integer count = merchantMapper.selectCount(new LambdaQueryWrapper<Merchant>()
                .eq(Merchant::getMobile, merchantDTO.getMobile()));
        if (count > 0) {
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        // 租户和账号绑定
        CreateTenantRequestDTO createTenantRequestDTO = new CreateTenantRequestDTO();
        createTenantRequestDTO.setMobile(merchantDTO.getMobile());
        createTenantRequestDTO.setTenantTypeCode("shanjupay-merchant");
        createTenantRequestDTO.setBundleCode("shanjupay-merchant");
        // 租户的账号信息
        createTenantRequestDTO.setUsername(merchantDTO.getUsername());
        createTenantRequestDTO.setPassword(merchantDTO.getPassword());

        createTenantRequestDTO.setName(merchantDTO.getUsername());
        log.info("商户中心调用统一账号服务，新增租户和账号");
        TenantDTO tenantDTO = tenantService.createTenantAndAccount(createTenantRequestDTO);

        if (tenantDTO == null || tenantDTO.getId() == null) {
            throw new BusinessException(CommonErrorCode.E_200012);
        }

        // 判断商户是否已经在SaaS中注册
        Merchant merchant = merchantMapper.selectOne(new QueryWrapper<Merchant>().lambda()
                .eq(Merchant::getTenantId, tenantDTO.getId()));

        if (merchant != null && merchant.getId() != null) {
            throw new BusinessException(CommonErrorCode.E_200017);
        }

        // 设置商户所属租户
        merchantDTO.setTenantId(tenantDTO.getId());
        // 设置审核状态
        merchantDTO.setAuditStatus("0");
        // 使用MapStruct将Dto转换成entity
        Merchant entity = MerchantConvert.INSTANCE.dto2entity(merchantDTO);
        // 保存商户
        log.info("保存商户信息");
        merchantMapper.insert(entity);

        // 新增门店
        StoreDTO storeDTO = new StoreDTO();
        storeDTO.setMerchantId(entity.getId());
        storeDTO.setStoreName("根门店");
        storeDTO = createStore(storeDTO);
        log.info("门店信息: {}" + JSON.toJSONString(storeDTO));

        // 新增员工， 并设置归属门店
        StaffDTO staffDTO = new StaffDTO();
        staffDTO.setMerchantId(entity.getId());
        staffDTO.setMobile(merchantDTO.getMobile());
        staffDTO.setUsername(merchantDTO.getUsername());
        // 为员工选择归属门店
        staffDTO.setStoreId(storeDTO.getId());
        staffDTO = createStaff(staffDTO);

        // 绑定员工和门店
        bindStaffToStore(storeDTO.getId(), staffDTO.getId());

        //
        // 将entity转换成dto
        return MerchantConvert.INSTANCE.entity2dto(entity);
    }

    /**
     * 商户资质注册
     * @param merchantId 商户ID
     * @param merchantDTO {@link MerchantDTO}
     * @throws BusinessException
     */
    @Override
    public void applyMerchant(Long merchantId, MerchantDTO merchantDTO) throws BusinessException {
        // 校验信息
        if (merchantDTO == null || merchantId == null) {
            throw new BusinessException(CommonErrorCode.E_300009);
        }
        // 根据商户id查询
        Merchant merchant = merchantMapper.selectById(merchantId);

        if (merchant == null) {
            throw new BusinessException(CommonErrorCode.E_200002);
        }

        // 更新商户资质审核数据
        Merchant merchant_update = MerchantConvert.INSTANCE.dto2entity(merchantDTO);
        merchant_update.setAuditStatus("1");
        // 租户id
        merchant_update.setId(merchant.getId());
        merchant_update.setMobile(merchant.getMobile());
        merchant_update.setTenantId(merchant.getTenantId());
        merchantMapper.updateById(merchant_update);
    }

    /**
     * 创建店铺store接口实现
     * @param storeDTO {@link StoreDTO}
     * @return {@link StoreDTO}
     * @throws BusinessException
     */
    @Override
    public StoreDTO createStore(StoreDTO storeDTO) throws BusinessException {
        Store store = StoreConvert.INSTANCE.dto2entity(storeDTO);
        storeMapper.insert(store);
        return StoreConvert.INSTANCE.entity2dto(store);
    }

    /**
     * 新建员工接口
     * @param staffDTO {@link StaffDTO}
     * @return
     * @throws BusinessException
     */
    @Override
    public StaffDTO createStaff(StaffDTO staffDTO) throws BusinessException {
        // 校验员工数据
        String mobile = staffDTO.getMobile();
        if (StringUtils.isBlank(mobile)) {
            throw new BusinessException(CommonErrorCode.E_100112);
        }
        // 校验唯一性
        String username = staffDTO.getUsername();

        if (isExistStaffByMobile(mobile, staffDTO.getMerchantId())) {
            throw new BusinessException(CommonErrorCode.E_100113);
        }
        if (isExistStaffByUsername(username, staffDTO.getMerchantId())) {
            throw new BusinessException(CommonErrorCode.E_100114);
        }

        Staff entity = StaffConvert.INSTANCE.dto2entity(staffDTO);
        staffMapper.insert(entity);
        return StaffConvert.INSTANCE.entity2dto(entity);
    }



    /**
     * 根据手机号判断员工是否已在指定商户存在
     * @param mobile 用户手机号
     * @param merchantId 商铺ID
     * @return int 查找结果
     */
    private boolean isExistStaffByMobile(String mobile, Long merchantId) {
        LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<Staff>();
        lambdaQueryWrapper.eq(Staff::getMobile, merchantId)
                .eq(Staff::getMerchantId, merchantId);
        int count = staffMapper.selectCount(lambdaQueryWrapper);
        return count > 0;
    }

    /**
     *根据账号判断员工是否已在指定商户存在
     * @param username 用户名
     * @param merchantId 商户ID
     * @return int
     */
    private boolean isExistStaffByUsername(String username, Long merchantId) {
        LambdaQueryWrapper<Staff> lambdaQueryWrapper = new LambdaQueryWrapper<Staff>();
        lambdaQueryWrapper.eq(Staff::getUsername, username)
                .eq(Staff::getMerchantId, merchantId);
        int count = staffMapper.selectCount(lambdaQueryWrapper);
        return count > 0;
    }

    /**
     * 门店设置管理员
     * @param storeId 商铺id
     * @param staffId 员工Id
     * @throws BusinessException
     */
    @Override
    public void bindStaffToStore(Long storeId, Long staffId) throws BusinessException {
        StoreStaff storeStaff = new StoreStaff();
        storeStaff.setStoreId(storeId);
        storeStaff.setStaffId(staffId);
        storeStaffMapper.insert(storeStaff);
    }
}
